#include "pch.h"
#include "endian_test.h"
#include <boostext/endian.hpp>




// When the system uses little endian byte ordering, then constructing
// a little_endian from a variable and from raw data should result in the
// same binary pattern.
//
// When the system uses big endian byte ordering, then they should be unequal,
// because the raw data is expected to be in little byte ordering (hence the name raw)
// however when the endianness from the raw-constructed little_endian object is swapped
// both should have the same binary pattern.
#ifdef BOOST_LITTLE_ENDIAN
	#define LITTLE_ENDIAN_TEST(type)   boostext::little_endian<type> tmp1(val); \
									   boostext::little_endian<type> tmp2 = boostext::little_endian<type>::raw(val); \
									   ASSERT( memcmp( &tmp1, &tmp2, sizeof(tmp1) ) == 0 ); \
									   ASSERT( tmp1 == val ); \
									   ASSERT( tmp2 == val );
#elif defined(BOOST_BIG_ENDIAN)
	#define LITTL_ENDIAN_TEST(type)    boostext::little_endian<type> tmp1(val); \
									   boostext::little_endian<type> tmp2 = boostext::little_endian<type>::raw(val); \
									   ASSERT( memcmp( &tmp1, &tmp2, sizeof(tmp1) ) != 0 ); \
									   type tmp3 = tmp2; \
									   boostext::endian_swap(tmp3); \
									   tmp2 = tmp3; \
									   ASSERT( memcmp( &tmp1, &tmp2, sizeof(tmp1) ) == 0 ); \
									   ASSERT( tmp1 == val ); \
									   ASSERT( tmp2 == val );
#else
	#error No endianness defined
#endif

// When the system uses big endian byte ordering, then constructing
// a big_endian from a variable and from raw data should result in the
// same binary pattern.
//
// When the system uses little endian byte ordering, then they should be unequal,
// because the raw data is expected to be in big byte ordering (hence the name raw)
// however when the endianness from the raw-constructed little_endian object is swapped
// both should have the same binary pattern.
#ifdef BOOST_BIG_ENDIAN
	#define BIG_ENDIAN_TEST(type)   boostext::big_endian<type> tmp1(val); \
									boostext::big_endian<type> tmp2 = boostext::big_endian<type>::raw(val); \
									ASSERT( memcmp( &tmp1, &tmp2, sizeof(tmp1) ) == 0 ); \
									ASSERT( tmp1 == val ); \
									ASSERT( tmp2 == val );
#elif defined(BOOST_LITTLE_ENDIAN)
	#define BIG_ENDIAN_TEST(type)    boostext::big_endian<type> tmp1(val); \
									 boostext::big_endian<type> tmp2 = boostext::big_endian<type>::raw(val); \
									 ASSERT( memcmp( &tmp1, &tmp2, sizeof(tmp1) ) != 0 ); \
									 type tmp3 = tmp2; \
									 boostext::endian_swap(tmp3); \
									 tmp2 = tmp3; \
									 ASSERT( memcmp( &tmp1, &tmp2, sizeof(tmp1) ) == 0 ); \
									 ASSERT( tmp1 == val ); \
									 ASSERT( tmp2 == val );
#else
	#error No endianness defined
#endif




void endian_test::little_endian()
{
	//
	// uint16
	//
	{
		uint16 val = 0xAFFE;
		LITTLE_ENDIAN_TEST(uint16);
	}

	//
	// int16
	//
	{
		int16 val = 5000;
		LITTLE_ENDIAN_TEST(int16);
	}

	//
	// uint32
	//
	{
		uint32 val = 0xAFFEAFFE;
		LITTLE_ENDIAN_TEST(uint32);
	}

	//
	// int32
	//
	{
		int32 val = 4000000;
		LITTLE_ENDIAN_TEST(int32);
	}


	//
	// uint64
	//
	{
		uint64 val = 0xAFFEAFFEAFFEAFFE;
		LITTLE_ENDIAN_TEST(uint64);
	}


	//
	// int64
	//
	{
		int64 val = 10000000000;
		LITTLE_ENDIAN_TEST(int64);
	}

	//
	// float
	//
	{
		float val = 5000.0f;
		LITTLE_ENDIAN_TEST(float);
	}

	//
	// double
	//
	{
		double val = 5000000.0;
		LITTLE_ENDIAN_TEST(double);
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void endian_test::big_endian()
{
	//
	// uint16
	//
	{
		uint16 val = 0xAFFE;
		BIG_ENDIAN_TEST(uint16);
	}

	//
	// int16
	//
	{
		int16 val = 5000;
		BIG_ENDIAN_TEST(int16);
	}

	//
	// uint32
	//
	{
		uint32 val = 0xAFFEAFFE;
		BIG_ENDIAN_TEST(uint32);
	}

	//
	// int32
	//
	{
		int32 val = 4000000;
		BIG_ENDIAN_TEST(int32);
	}

	//
	// uint64
	//
	{
		uint64 val = 0xAFFEAFFEAFFEAFFE;
		BIG_ENDIAN_TEST(uint64);
	}

	//
	// int64
	//
	{
		int64 val = 10000000000;
		BIG_ENDIAN_TEST(int64);
	}

	//
	// float
	//
	{
		float val = 5000.0f;
		BIG_ENDIAN_TEST(float);
	}

	//
	// double
	//
	{
		double val = 5000000.0;
		BIG_ENDIAN_TEST(double);
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////




void endian_test::operator()()
{
	little_endian();
	big_endian();
}
///////////////////////////////////////////////////////////////////////////////////////////////////
